package com.fg.pro.trade.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fg.pro.model.exception.CustomException;
import com.fg.pro.model.utils.PoiUtils;
import com.fg.pro.trade.dao.TradeStockDao;
import com.fg.pro.trade.entity.TradeCategory;
import com.fg.pro.trade.entity.TradeGoods;
import com.fg.pro.trade.entity.TradeStock;
import com.fg.pro.trade.service.TradeCategoryService;
import com.fg.pro.trade.service.TradeGoodsService;
import com.fg.pro.trade.service.TradeStockService;
import com.fg.pro.trade.service.TradeStockSheetService;
import com.fg.pro.trade.utils.GmHttpUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.fg.pro.model.enums.AppHttpCodeEnum.GOODS_CATEGORY_ERROR_NOT_BLANK;
import static com.fg.pro.model.enums.AppHttpCodeEnum.GOODS_ERROR_NOT_BLANK;
import static com.fg.pro.trade.utils.GmRequestUrl.*;

/**
 * 商品_货值(TradeStock)表服务实现类
 *
 * @author makejava
 * @since 2025-08-20 10:10:15
 */
@Slf4j
@Service("tradeStockService")
public class TradeStockServiceImpl extends ServiceImpl<TradeStockDao, TradeStock> implements TradeStockService {
    @Autowired
    RedissonClient redissonClient;

    @Resource
    private TradeGoodsService tradeGoodsService;
    @Resource
    private PoiUtils poiUtils;
    @Resource
    private TradeCategoryService tradeCategoryService;
    @Override
    public Boolean upload(MultipartFile multipartFile, Date date) {
        RLock lock = redissonClient.getLock(REDIS_LOCK_URL+ "uploadStockExcel");
        boolean tryLock = lock.tryLock();
        if(!tryLock){
            return false;
        }
        try {
            return uploadStockExcel(multipartFile,date);
        } catch (RuntimeException | IOException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    private Boolean uploadStockExcel(MultipartFile multipartFile,Date date) throws IOException {
        Workbook workbook = new XSSFWorkbook(multipartFile.getInputStream());
        // 1 将excel转换成list数据
        Sheet sheetAt = workbook.getSheetAt(0);
        int lastRowNum = sheetAt.getLastRowNum();
        Row row = null;
        LinkedList<TradeStock> newStockList = new LinkedList<>();
        Map<String, Long> idAndCodeMap = tradeGoodsService.getIdAndCode();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = dateFormat.format(date);
        List<TradeCategory> tradeCategoryList = tradeCategoryService.query().list();
        for (int i = 1; i <= lastRowNum; i++) {
            row = sheetAt.getRow(i);
            TradeStock tradeStock = new TradeStock();

//            id	主键
//            goods_id	商品id
            if (row.getCell(0) != null) {
                String goodsCode = poiUtils.getStringByCellIndex(row,0);
                if(goodsCode.equals("xjbs2755")){
                    break;
                }
                Long goodsId = idAndCodeMap.get(goodsCode);
                if (goodsId == null) {
                    log.info("----------------------------------------------"+goodsCode);
                    log.info(String.valueOf(i));
                    throw new CustomException(GOODS_ERROR_NOT_BLANK);
                }
                tradeStock.setGoodsId(goodsId);
            }

//            goods_name	商品名称
            if (row.getCell(1) != null) {
                String goodsName = poiUtils.getStringByCellIndex(row,1);
                tradeStock.setGoodsName(goodsName);
            }
//            goods_base_unit_name	基本单位
            if (row.getCell(4) != null) {
                tradeStock.setGoodsBaseUnitName(poiUtils.getStringByCellIndex(row,4));
            }
//            stock_name	仓库
            if (row.getCell(2) != null) {
                tradeStock.setStockName(poiUtils.getStringByCellIndex(row,2));
            }
//            category_id	分类id
//            category_name	商品分类
            if (row.getCell(3) != null) {
                String categoryName = row.getCell(3).getStringCellValue().trim();
//                Long categoryId = getIdAndNameMap.get(categoryName);
                if(categoryName.contains("/")){
                    String categoryFirName = categoryName.split("/")[0];
                    String categorySecName = categoryName.split("/")[1];
                    List<TradeCategory> categoryFirList = tradeCategoryList.stream().filter(item -> {
                        return item.getCategoryLev() == 1 && item.getCategoryName().equals(categoryFirName);
                    }).collect(Collectors.toList());
                    if(categoryFirList.isEmpty()){
                        throw new CustomException(GOODS_CATEGORY_ERROR_NOT_BLANK);
                    }
                    List<TradeCategory> categorySecList = tradeCategoryList.stream().filter(item -> {
                        return item.getCategoryLev() == 2 && item.getCategoryName().equals(categorySecName);
                    }).collect(Collectors.toList());
                    if(categorySecList.isEmpty()){
                        throw new CustomException(GOODS_CATEGORY_ERROR_NOT_BLANK);
                    }
                    tradeStock.setCategoryFirId(categoryFirList.get(0).getId());
                    tradeStock.setCategoryFirName(categoryFirName);
                    tradeStock.setCategorySecId(categorySecList.get(0).getId());
                    tradeStock.setCategorySecName(categorySecName);
                }else {
                    List<TradeCategory> categoryFirList = tradeCategoryList.stream().filter(item -> {
                        return item.getCategoryLev() == 1 && item.getCategoryName().equals(categoryName);
                    }).collect(Collectors.toList());
                    if(categoryFirList.isEmpty()){
                        throw new CustomException(GOODS_CATEGORY_ERROR_NOT_BLANK);
                    }
                    tradeStock.setCategoryFirId(categoryFirList.get(0).getId());
                    tradeStock.setCategoryFirName(categoryName);
                }
            }

//            create_time
            tradeStock.setCreateTime(date);

//            stock_initial_stock	期初库存
            Cell cell5 = row.getCell(5);
            cell5.setCellType(CellType.STRING);
            if (cell5 != null) {
//                tradeStock.setStockInitialStock(getDoubleByString(cell5.getStringCellValue().trim()));
                tradeStock.setStockInitialStock(poiUtils.getDoubleByCellIndex(row,5));
            }

//            stock_initial_value	期初货值 6
            Cell cell6 = row.getCell(6);
            cell6.setCellType(CellType.STRING);
            if (cell6 != null) {
//                tradeStock.setStockInitialValue(getDoubleByString(cell6.getStringCellValue().trim()));
                tradeStock.setStockInitialValue(poiUtils.getDoubleByCellIndex(row,6));
            }

//            stock_initial_ave_price	期初均价 7
            Cell cell7 = row.getCell(7);
            cell7.setCellType(CellType.STRING);
            if (cell7 != null) {
//                tradeStock.setStockInitialAvePrice(getDoubleByString(cell7.getStringCellValue().trim()));
                tradeStock.setStockInitialAvePrice(poiUtils.getDoubleByCellIndex(row,7));
            }
//            stock_end_stock	期末库存 8
            Cell cell8 = row.getCell(8);
            cell8.setCellType(CellType.STRING);
            if (cell8 != null) {
//                tradeStock.setStockEndStock(getDoubleByString(cell8.getStringCellValue().trim()));
                tradeStock.setStockEndStock(poiUtils.getDoubleByCellIndex(row,8));
            }
//            stock_over_stock	超支库存 9
            Cell cell9 = row.getCell(9);
            cell9.setCellType(CellType.STRING);
            if (cell9 != null) {
//                tradeStock.setStockOverStock(getDoubleByString(cell9.getStringCellValue().trim()));
                tradeStock.setStockOverStock(poiUtils.getDoubleByCellIndex(row,9));
            }
//            stock_end_value	期末货值 10
            Cell cell10 = row.getCell(10);
            cell10.setCellType(CellType.STRING);
            if (cell10 != null) {
//                tradeStock.setStockEndValue(getDoubleByString(cell10.getStringCellValue().trim()));
                tradeStock.setStockEndValue(poiUtils.getDoubleByCellIndex(row,10));
            }
//            stock_end_ave_price	期末均价 11
            Cell cell11 = row.getCell(11);
            cell11.setCellType(CellType.STRING);
            if (cell11 != null) {
//                tradeStock.setStockEndAvePrice(getDoubleByString(cell11.getStringCellValue().trim()));
                tradeStock.setStockEndAvePrice(poiUtils.getDoubleByCellIndex(row,11));
            }
//            stock_in_purchase_num	本期采购入库数量 12
            Cell cell12 = row.getCell(12);
            cell12.setCellType(CellType.STRING);
            if (cell12 != null) {
//                tradeStock.setStockInPurchaseNum(getDoubleByString(cell12.getStringCellValue().trim()));
                tradeStock.setStockInPurchaseNum(poiUtils.getDoubleByCellIndex(row,12));
            }
//            stock_in_purchase_cost	本期入库成本 13
            Cell cell13 = row.getCell(13);
            cell13.setCellType(CellType.STRING);
            if (cell13 != null) {
//                tradeStock.setStockInPurchaseCost(getDoubleByString(cell13.getStringCellValue().trim()));
                tradeStock.setStockInPurchaseCost(poiUtils.getDoubleByCellIndex(row,13));
            }
//            stock_out_purchase_return_num	本期采购退货出库数量 14
            Cell cell14 = row.getCell(14);
            cell14.setCellType(CellType.STRING);
            if (cell14 != null) {
//                tradeStock.setStockOutPurchaseReturnNum(getDoubleByString(cell14.getStringCellValue().trim()));
                tradeStock.setStockOutPurchaseReturnNum(poiUtils.getDoubleByCellIndex(row,14));
            }
//            stock_out_purchase_return_price	本期采购退货出金额 15
            Cell cell15 = row.getCell(15);
            cell15.setCellType(CellType.STRING);
            if (cell15 != null) {
//                tradeStock.setStockOutPurchaseReturnPrice(getDoubleByString(cell15.getStringCellValue().trim()));
                tradeStock.setStockOutPurchaseReturnPrice(poiUtils.getDoubleByCellIndex(row,15));
            }
//            stock_out_sale_num	本期销售出库数量 16
            Cell cell16 = row.getCell(16);
            cell16.setCellType(CellType.STRING);
            if (cell16 != null) {
//                tradeStock.setStockOutSaleNum(getDoubleByString(cell16.getStringCellValue().trim()));
                tradeStock.setStockOutSaleNum(poiUtils.getDoubleByCellIndex(row,16));
            }
//            stock_out_sale_price	本期销售出库金额 17
            Cell cell17 = row.getCell(17);
            cell17.setCellType(CellType.STRING);
            if (cell17 != null) {
//                tradeStock.setStockOutSalePrice(getDoubleByString(cell17.getStringCellValue().trim()));
                tradeStock.setStockOutSalePrice(poiUtils.getDoubleByCellIndex(row,17));
            }
//            stock_in_sale_return_num	本期销售退货入库数量 18
            Cell cell18 = row.getCell(18);
            cell18.setCellType(CellType.STRING);
            if (cell18 != null) {
//                tradeStock.setStockInSaleReturnNum(getDoubleByString(cell18.getStringCellValue().trim()));
                tradeStock.setStockInSaleReturnNum(poiUtils.getDoubleByCellIndex(row,18));
            }
//            stock_in_sale_return_price	本期销售退货入库金额 19
            Cell cell19 = row.getCell(19);
            cell19.setCellType(CellType.STRING);
            if (cell19 != null) {
//                tradeStock.setStockInSaleReturnPrice(getDoubleByString(cell19.getStringCellValue().trim()));
                tradeStock.setStockInSaleReturnPrice(poiUtils.getDoubleByCellIndex(row,19));
            }
//            stock_out_picking_num	本期领料出库数量 20
            Cell cell20 = row.getCell(20);
            cell20.setCellType(CellType.STRING);
            if (cell20 != null) {
//                tradeStock.setStockOutPickingNum(getDoubleByString(cell20.getStringCellValue().trim()));
                tradeStock.setStockOutPickingNum(poiUtils.getDoubleByCellIndex(row,20));
            }
//            stock_out_picking_price	本期领料出库金额 21
            Cell cell21 = row.getCell(21);
            cell21.setCellType(CellType.STRING);
            if (cell21 != null) {
//                tradeStock.setStockOutPickingPrice(getDoubleByString(cell21.getStringCellValue().trim()));
                tradeStock.setStockOutPickingPrice(poiUtils.getDoubleByCellIndex(row,21));
            }
//            stock_in_picking_return_num	本期退料入库数量 22
            Cell cell22 = row.getCell(22);
            cell22.setCellType(CellType.STRING);
            if (cell22 != null) {
//                tradeStock.setStockInPickingReturnNum(getDoubleByString(cell22.getStringCellValue().trim()));
                tradeStock.setStockInPickingReturnNum(poiUtils.getDoubleByCellIndex(row,22));
            }
//            stock_in_picking_return_price	本期退料入库金额 23
            Cell cell23 = row.getCell(23);
            cell23.setCellType(CellType.STRING);
            if (cell23 != null) {
//                tradeStock.setStockInPickingReturnPrice(getDoubleByString(cell23.getStringCellValue().trim()));
                tradeStock.setStockInPickingReturnPrice(poiUtils.getDoubleByCellIndex(row,23));
            }
//            stock_in_make_num	本期生产入库数量 24
            Cell cell24 = row.getCell(24);
            cell24.setCellType(CellType.STRING);
            if (cell24 != null) {
//                tradeStock.setStockInMakeNum(getDoubleByString(cell24.getStringCellValue().trim()));
                tradeStock.setStockInMakeNum(poiUtils.getDoubleByCellIndex(row,24));
            }
//            stock_in_make_price	本期生产入库金额 25
            Cell cell25 = row.getCell(25);
            cell25.setCellType(CellType.STRING);
            if (cell25 != null) {
//                tradeStock.setStockInMakePrice(getDoubleByString(cell25.getStringCellValue().trim()));
                tradeStock.setStockInMakePrice(poiUtils.getDoubleByCellIndex(row,25));
            }
//            stock_in_overflow_num	本期盘盈入库数量 26
            Cell cell26 = row.getCell(26);
            cell26.setCellType(CellType.STRING);
            if (cell26 != null) {
//                tradeStock.setStockInOverflowNum(getDoubleByString(cell26.getStringCellValue().trim()));
                tradeStock.setStockInOverflowNum(poiUtils.getDoubleByCellIndex(row,26));
            }
//            stock_in_overflow_price	本期盘盈入库金额 27
            Cell cell27 = row.getCell(27);
            cell27.setCellType(CellType.STRING);
            if (cell27 != null) {
//                tradeStock.setStockInOverflowPrice(getDoubleByString(cell27.getStringCellValue().trim()));
                tradeStock.setStockInOverflowPrice(poiUtils.getDoubleByCellIndex(row,27));
            }
//            stock_in_adjustment_num	本期调拨入库数量 28
            Cell cell28 = row.getCell(28);
            cell28.setCellType(CellType.STRING);
            if (cell28 != null) {
//                tradeStock.setStockInAdjustmentNum(getDoubleByString(cell28.getStringCellValue().trim()));
                tradeStock.setStockInAdjustmentNum(poiUtils.getDoubleByCellIndex(row,28));
            }
//            stock_in_adjustment_price	本期调拨入库金额 29
            Cell cell29 = row.getCell(29);
            cell29.setCellType(CellType.STRING);
            if (cell29 != null) {
//                tradeStock.setStockInAdjustmentPrice(getDoubleByString(cell29.getStringCellValue().trim()));
                tradeStock.setStockInAdjustmentPrice(poiUtils.getDoubleByCellIndex(row,29));
            }
//            stock_in_disassembly_num	本期组装拆卸入库数量 32
            Cell cell32 = row.getCell(32);
            cell32.setCellType(CellType.STRING);
            if (cell32 != null) {
//                tradeStock.setStockInDisassemblyNum(getDoubleByString(cell32.getStringCellValue().trim()));
                tradeStock.setStockInDisassemblyNum(poiUtils.getDoubleByCellIndex(row,32));
            }
//            stock_in_disassembly_price	本期组装拆卸入库金额 33
            Cell cell33 = row.getCell(33);
            cell33.setCellType(CellType.STRING);
            if (cell33 != null) {
//                tradeStock.setStockInDisassemblyPrice(getDoubleByString(cell33.getStringCellValue().trim()));
                tradeStock.setStockInDisassemblyPrice(poiUtils.getDoubleByCellIndex(row,33));
            }
//            stock_out_loss_num	本期盘亏出库数量 34
            Cell cell34 = row.getCell(34);
            cell34.setCellType(CellType.STRING);
            if (cell34 != null) {
//                tradeStock.setStockOutLossNum(getDoubleByString(cell34.getStringCellValue().trim()));
                tradeStock.setStockOutLossNum(poiUtils.getDoubleByCellIndex(row,34));
            }
//            stock_out_loss_price	本期盘亏出库金额 35
            Cell cell35 = row.getCell(35);
            cell35.setCellType(CellType.STRING);
            if (cell35 != null) {
//                tradeStock.setStockOutLossPrice(getDoubleByString(cell35.getStringCellValue().trim()));
                tradeStock.setStockOutLossPrice(poiUtils.getDoubleByCellIndex(row,35));
            }
//            stock_in_other_num	本期其他入库数量 36
            Cell cell36 = row.getCell(36);
            cell36.setCellType(CellType.STRING);
            if (cell36 != null) {
//                tradeStock.setStockInOtherNum(getDoubleByString(cell36.getStringCellValue().trim()));
                tradeStock.setStockInOtherNum(poiUtils.getDoubleByCellIndex(row,36));
            }
//            stock_in_other_price	本期其他入库金额 37
            Cell cell37 = row.getCell(37);
            cell37.setCellType(CellType.STRING);
            if (cell37 != null) {
//                tradeStock.setStockInOtherPrice(getDoubleByString(cell37.getStringCellValue().trim()));
                tradeStock.setStockInOtherPrice(poiUtils.getDoubleByCellIndex(row,37));
            }
//            stock_out_other_num	本期其他出库数量 38
            Cell cell38 = row.getCell(38);
            cell38.setCellType(CellType.STRING);
            if (cell38 != null) {
//                tradeStock.setStockOutOtherNum(getDoubleByString(cell38.getStringCellValue().trim()));
                tradeStock.setStockOutOtherNum(poiUtils.getDoubleByCellIndex(row,38));
            }
//            stock_out_other_price	本期其他出库金额 39
            Cell cell39 = row.getCell(39);
            cell39.setCellType(CellType.STRING);
            if (cell39 != null) {
//                tradeStock.setStockOutOtherPrice(getDoubleByString(cell39.getStringCellValue().trim()));
                tradeStock.setStockOutOtherPrice(poiUtils.getDoubleByCellIndex(row,39));
            }
//            stock_out_adjustment_num	本期调拨出库数量 40
            Cell cell40 = row.getCell(40);
            cell40.setCellType(CellType.STRING);
            if (cell40 != null) {
//                tradeStock.setStockOutAdjustmentNum(getDoubleByString(cell40.getStringCellValue().trim()));
                tradeStock.setStockOutAdjustmentNum(poiUtils.getDoubleByCellIndex(row,40));
            }
//            stock_out_adjustment_price	本期调拨出库金额 41
            Cell cell41 = row.getCell(41);
            cell41.setCellType(CellType.STRING);
            if (cell41 != null) {
//                tradeStock.setStockOutAdjustmentPrice(getDoubleByString(cell41.getStringCellValue().trim()));
                tradeStock.setStockOutAdjustmentPrice(poiUtils.getDoubleByCellIndex(row,41));
            }
//            stock_out_disassembly_num	本期组装拆卸出库数量 42
            Cell cell42 = row.getCell(42);
            cell42.setCellType(CellType.STRING);
            if (cell42 != null) {
//                tradeStock.setStockOutDisassemblyNum(getDoubleByString(cell42.getStringCellValue().trim()));
                tradeStock.setStockOutDisassemblyNum(poiUtils.getDoubleByCellIndex(row,42));
            }
//            stock_out_disassembly_price	本期组装拆卸出库金额 43
            Cell cell43 = row.getCell(43);
            cell43.setCellType(CellType.STRING);
            if (cell43 != null) {
//                tradeStock.setStockOutDisassemblyPrice(getDoubleByString(cell43.getStringCellValue().trim()));
                tradeStock.setStockOutDisassemblyPrice(poiUtils.getDoubleByCellIndex(row,43));
            }

            newStockList.add(tradeStock);
        }
        // 2.1 删除当日旧数据
        QueryWrapper<TradeStock> queryWrapper = new QueryWrapper<TradeStock>().eq("create_time", dateStr);
        boolean remove = remove(queryWrapper);

        // 2.2 添加当日新数据
        boolean saveBatch = saveBatch(newStockList);
        return saveBatch;
    }

    @Override
    public PageInfo getPage(Integer pageNum, Integer pageSize, Date startDate, Date endDate, String goodsName) {
        SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd");
        String startStr = sdfs.format(cn.hutool.core.date.DateUtil.beginOfDay(startDate));
        String endStr = sdfs.format(DateUtil.endOfDay(endDate));
        PageHelper.startPage(pageNum, pageSize);
        List<TradeStock> stockList = query()
                .like(StrUtil.isNotBlank(goodsName),"goods_name",goodsName)
                .ge("create_time", startStr).le("create_time", endStr).orderByDesc("create_time")
                .list();
        PageInfo<TradeStock> pageInfo= new PageInfo(stockList);
        return pageInfo;
    }
}

